#include <iostream>
#include <vector>
#include <pthread.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "Task.hpp"

const int cdefaultnum = 5;

// 管道
class Channel
{
public:
    Channel(pid_t pid, int wfd) : _pid(pid), _wfd(wfd)
    {
        _name = "channel - " + std::to_string(pid) + " - " + std::to_string(wfd);
    }

    // 发送数据
    void Send(int data)
    {
        std::cout << "send taskcode: " << data << std::endl;
        write(_wfd, &data, sizeof(int));
    }

    __pid_t GetPid() const
    {
        return _pid;
    }

    const std::string &GetName() const
    {
        return _name;
    }

    // 关闭父进程wfd
    void ChannelClose()
    {
        int n = close(_wfd);
    }

    // 等待子进程结束
    void ChannelWait()
    {
        pid_t n = waitpid(_pid, nullptr, 0);
    }

    ~Channel() {}

private:
    pid_t _pid;
    int _wfd;
    std::string _name;
};

// 父进程，管道管理器
class ChannelManager
{
public:
    ChannelManager() {}

    // 创建管道
    void Insert(pid_t pid, int wfd)
    {
        _channels.emplace_back(pid, wfd);
        /*Channel c(pid, wfd);
        _channels.push_back(c);*/
    }

    Channel &Select()
    {
        auto &c = _channels[_index];

        _index = (_index + 1) % _channels.size();
        return c;
    }

    // 关闭所有管道
    void StopSubProcess()
    {
        for (auto &c : _channels)
        {
            std::cout << "close channel name: " << c.GetName() << std::endl;
            c.ChannelClose();
        }
    }

    // 等待所有子进程结束
    void WaitSubProcess()
    {
        for (auto &c : _channels)
        {
            std::cout << "wait channel name: " << c.GetName() << std::endl;
            c.ChannelWait();
        }
    }

    ~ChannelManager() {}

private:
    int _index = 0;                 // 管道索引
    std::vector<Channel> _channels; // 管道数量
};

// 进程池
class ProcessPool
{
public:
    // 构造函数，载入各任务
    ProcessPool(int num) : _process_num(num)
    {
        _tm.TaskRegister(PrintLog);
        _tm.TaskRegister(Download);
        _tm.TaskRegister(Upload);
    }

    // 子进程工作函数
    void work(int rfd)
    {
        while (true)
        {
            // std::cout << "child process work" << std::endl;

            int code = 0; // 初始化任务码
            ssize_t n = read(rfd, &code, sizeof(code));
            if (n < 0)
            {
                std::cout << "read error" << std::endl;
                break;
            }
            else if (n == 0)
            {
                std::cout << "read end" << std::endl;
                break;
            }
            else
            {
                if (n != sizeof(code))
                {
                    continue;
                }
                std::cout << "child process pid: " << getpid()
                          << " receive task code: " << code << std::endl;
                _tm.TaskExecute(code); // 执行任务

                std::cout << std::endl;
            }
        }
    }

    // 进程池创建
    bool create()
    {
        for (int i = 0; i < _process_num; i++)
        {
            // 创建管道
            int pipefd[2];
            int n = pipe(pipefd);
            if (n < 0)
            {
                std::cout << "pipe error" << std::endl;
                return false;
            }

            int pid = fork();
            if (pid < 0) // 创建失败
            {
                std::cout << "fork error" << std::endl;
                return false;
            }
            else if (pid == 0)
            {
                // 子进程
                close(pipefd[1]);

                work(pipefd[0]);

                close(pipefd[0]);
                exit(0);
            }
            else
            {
                // 父进程
                close(pipefd[0]);

                _cm.Insert(pid, pipefd[1]);
            }
        }

        return true;
    }

    // 传送任务码
    void run()
    {
        // 生成任务码
        int taskcode = _tm.code();

        // 轮询选择管道
        auto &c = _cm.Select();
        std::cout << "select channel name: " << c.GetName() << std::endl;

        // 发送任务码
        c.Send(taskcode);
    }

    // 进程池关闭
    void Stop()
    {
        std::cout << "stop process pool" << std::endl;

        // 子进程结束
        _cm.StopSubProcess();

        // 等待子进程结束
        _cm.WaitSubProcess();
    }

    ~ProcessPool() {}

private:
    TaskManager _tm;    // 任务管理器
    ChannelManager _cm; // 管道管理器
    int _process_num;   // 进程数量
};